
#include "synopGMAC_network_interface.h"


//sw:	ioctl in linux 		to be fixed
#define SIOCDEVPRIVATE	0x89f0
#define IOCTL_READ_REGISTER  SIOCDEVPRIVATE+1
#define IOCTL_WRITE_REGISTER SIOCDEVPRIVATE+2
#define IOCTL_READ_IPSTRUCT  SIOCDEVPRIVATE+3
#define IOCTL_READ_RXDESC    SIOCDEVPRIVATE+4
#define IOCTL_READ_TXDESC    SIOCDEVPRIVATE+5
#define IOCTL_POWER_DOWN     SIOCDEVPRIVATE+6


//static struct timer_list synopGMAC_cable_unplug_timer;
static u32 GMAC_Power_down; // This global variable is used to indicate the ISR whether the interrupts occured in the process of powering down the mac or not


/*These are the global pointers for their respecive structures*/
/*
extern struct synopGMACNetworkAdapter * synopGMACadapter;
extern synopGMACdevice	          * synopGMACdev;
//extern struct net_dev             * synopGMACnetdev;
//extern struct pci_dev             * synopGMACpcidev;
extern struct Pmon_Inet		  * PInetdev;
*/

//synopGMACdevice	          * synopGMACdev;
//extern struct net_dev             * synopGMACnetdev;
//extern struct pci_dev             * synopGMACpcidev;
//extern struct Pmon_Inet		  * PInetdev;



/*these are the global data for base address and its size*/
//extern u8* synopGMACMappedAddr;
//extern u32 synopGMACMappedAddrSize;
//extern u32 synop_pci_using_dac;

u32 synop_pci_using_dac = 0;
//#define MAC_ADDR {0x00, 0x55, 0x7B, 0xB5, 0x7D, 0xF7}	//sw: may be it should be F7 7D B5 7B 55 00
//#define MAC_ADDR {0x00, 0x56, 0x7B, 0xB5, 0x7D, 0xF9}	//sw: may be it should be F7 7D B5 7B 55 00

//u64 regbase = 0x90000d0000000000;	// this is of no use in this driver! liyifu on 2010-01-12

//void dumppkghd(struct ether_header *eh,int tp);
int set_lpmode(synopGMACdevice * gmacdev);
int set_phyled(synopGMACdevice * gmacdev);

unsigned int rx_test_count = 0;
unsigned int tx_normal_test_count = 0;
unsigned int tx_abnormal_test_count = 0;
unsigned int tx_stopped_test_count = 0;





/*Sample Wake-up frame filter configurations*/

u32 synopGMAC_wakeup_filter_config0[] = {
					0x00000000,	// For Filter0 CRC is not computed may be it is 0x0000
					0x00000000,	// For Filter1 CRC is not computed may be it is 0x0000
					0x00000000,	// For Filter2 CRC is not computed may be it is 0x0000
					0x5F5F5F5F,     // For Filter3 CRC is based on 0,1,2,3,4,6,8,9,10,11,12,14,16,17,18,19,20,22,24,25,26,27,28,30 bytes from offset
					0x09000000,     // Filter 0,1,2 are disabled, Filter3 is enabled and filtering applies to only multicast packets
					0x1C000000,     // Filter 0,1,2 (no significance), filter 3 offset is 28 bytes from start of Destination MAC address
					0x00000000,     // No significance of CRC for Filter0 and Filter1
					0xBDCC0000      // No significance of CRC for Filter2, Filter3 CRC is 0xBDCC
					};
u32 synopGMAC_wakeup_filter_config1[] = {
					0x00000000,	// For Filter0 CRC is not computed may be it is 0x0000
					0x00000000,	// For Filter1 CRC is not computed may be it is 0x0000
					0x7A7A7A7A,	// For Filter2 CRC is based on 1,3,4,5,6,9,11,12,13,14,17,19,20,21,25,27,28,29,30 bytes from offset
					0x00000000,     // For Filter3 CRC is not computed may be it is 0x0000
					0x00010000,     // Filter 0,1,3 are disabled, Filter2 is enabled and filtering applies to only unicast packets
					0x00100000,     // Filter 0,1,3 (no significance), filter 2 offset is 16 bytes from start of Destination MAC address
					0x00000000,     // No significance of CRC for Filter0 and Filter1
					0x0000A0FE      // No significance of CRC for Filter3, Filter2 CRC is 0xA0FE
					};
u32 synopGMAC_wakeup_filter_config2[] = {
					0x00000000,	// For Filter0 CRC is not computed may be it is 0x0000
					0x000000FF,	// For Filter1 CRC is computed on 0,1,2,3,4,5,6,7 bytes from offset
					0x00000000,	// For Filter2 CRC is not computed may be it is 0x0000
					0x00000000,     // For Filter3 CRC is not computed may be it is 0x0000
					0x00000100,     // Filter 0,2,3 are disabled, Filter 1 is enabled and filtering applies to only unicast packets
					0x0000DF00,     // Filter 0,2,3 (no significance), filter 1 offset is 223 bytes from start of Destination MAC address
					0xDB9E0000,     // No significance of CRC for Filter0, Filter1 CRC is 0xDB9E
					0x00000000      // No significance of CRC for Filter2 and Filter3
					};

/*
The synopGMAC_wakeup_filter_config3[] is a sample configuration for wake up filter.
Filter1 is used here
Filter1 offset is programmed to 50 (0x32)
Filter1 mask is set to 0x000000FF, indicating First 8 bytes are used by the filter
Filter1 CRC= 0x7EED this is the CRC computed on data 0x55 0x55 0x55 0x55 0x55 0x55 0x55 0x55

Refer accompanied software DWC_gmac_crc_example.c for CRC16 generation and how to use the same.
*/

u32 synopGMAC_wakeup_filter_config3[] = {
					0x00000000,	// For Filter0 CRC is not computed may be it is 0x0000
					0x000000FF,	// For Filter1 CRC is computed on 0,1,2,3,4,5,6,7 bytes from offset
					0x00000000,	// For Filter2 CRC is not computed may be it is 0x0000
					0x00000000,     // For Filter3 CRC is not computed may be it is 0x0000
					0x00000100,     // Filter 0,2,3 are disabled, Filter 1 is enabled and filtering applies to only unicast packets
					0x00003200,     // Filter 0,2,3 (no significance), filter 1 offset is 50 bytes from start of Destination MAC address
					0x7eED0000,     // No significance of CRC for Filter0, Filter1 CRC is 0x7EED,
					0x00000000      // No significance of CRC for Filter2 and Filter3
					};
/**
 * Function used to detect the cable plugging and unplugging.
 * This function gets scheduled once in every second and polls
 * the PHY register for network cable plug/unplug. Once the
 * connection is back the GMAC device is configured as per
 * new Duplex mode and Speed of the connection.
 * @param[in] u32 type but is not used currently.
 * \return returns void.
 * \note This function is tightly coupled with Linux 2.6.xx.
 * \callgraph
 */

/*
 * bcm5461 phy
 */

#define MII_BCM54XX_ECR		0x10	/* BCM54xx extended control register */
#define MII_BCM54XX_ECR_IM	0x1000	/* Interrupt mask */
#define MII_BCM54XX_ECR_IF	0x0800	/* Interrupt force */

#define MII_BCM54XX_ESR		0x11	/* BCM54xx extended status register */
#define MII_BCM54XX_ESR_IS	0x1000	/* Interrupt status */

#define MII_BCM54XX_ISR		0x1a	/* BCM54xx interrupt status register */
#define MII_BCM54XX_IMR		0x1b	/* BCM54xx interrupt mask register */
#define MII_BCM54XX_INT_CRCERr	0x0001	/* CRC error */
#define MII_BCM54XX_INT_LINK	0x0002	/* Link status changed */
#define MII_BCM54XX_INT_SPEED	0x0004	/* Link speed change */
#define MII_BCM54XX_INT_DUPLEX	0x0008	/* Duplex mode changed */
#define MII_BCM54XX_INT_LRS	0x0010	/* Local receiver status changed */
#define MII_BCM54XX_INT_RRS	0x0020	/* Remote receiver status changed */
#define MII_BCM54XX_INT_SSERR	0x0040	/* Scrambler synchronization error */
#define MII_BCM54XX_INT_UHCD	0x0080	/* Unsupported HCD negotiated */
#define MII_BCM54XX_INT_NHCD	0x0100	/* No HCD */
#define MII_BCM54XX_INT_NHCDL	0x0200	/* No HCD link */
#define MII_BCM54XX_INT_ANPR	0x0400	/* Auto-negotiation page received */
#define MII_BCM54XX_INT_LC	0x0800	/* All counters below 128 */
#define MII_BCM54XX_INT_HC	0x1000	/* Counter above 32768 */
#define MII_BCM54XX_INT_MDIX	0x2000	/* MDIX status change */
#define MII_BCM54XX_INT_PSERR	0x4000	/* Pair swap error */


static int rtl88e1111_config_init(synopGMACdevice *gmacdev)
{
	int retval, err;
	u16 data;

#if 0
	retval = synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,MII_BCM54XX_ECR,&data);
	if (retval < 0)
		return retval;

	/* Mask interrupts globally.  */
	data |= MII_BCM54XX_ECR_IM;
	err = synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,MII_BCM54XX_ECR,data);
	if (err < 0)
		return err;
#endif
	/* Unmask events we are interested in.  */
	/*
	data = ~(MII_BCM54XX_INT_DUPLEX |
		MII_BCM54XX_INT_SPEED |
		MII_BCM54XX_INT_LINK);
		*/
	//data = 0x6400;
	//data = 0x0;


	synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x14,&data);
	data = data | 0x82;
	err = synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x14,data);
	synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x00,&data);
	data = data | 0x8000;
	err = synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x00,data);
#if SYNOP_PHY_LOOPBACK
	synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x14,&data);
	data = data | 0x70;
	data = data & 0xffdf;
	err = synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x14,data);
	data = 0x8000;
	err = synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x00,data);
	data = 0x5140;
	err = synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x00,data);
#endif

       /*init link and act indication leds*/
           synopGMAC_read_phy_reg((u32 *) gmacdev->MacBase, gmacdev->PhyBase,
                                  PHY_LED_CONTROL, &data);
       data = (data | 0x51) &0xf4ff;
           synopGMAC_write_phy_reg((u32 *) gmacdev->MacBase, gmacdev->PhyBase,
                                   PHY_LED_CONTROL, data);
	if (err < 0)
		return err;
	return 0;
}
#include "mii.h"
#include "mii.c"


s32 synopGMAC_check_phy_init (synopGMACPciNetworkAdapter *adapter)
{
struct ethtool_cmd cmd;
synopGMACdevice            *gmacdev = adapter->synopGMACdev;



	if(!mii_link_ok(&adapter->mii))
	{
		gmacdev->DuplexMode = FULLDUPLEX;
		gmacdev->Speed      =   SPEED100;

		return 0;
	}
	else

	{
		mii_ethtool_gset(&adapter->mii, &cmd);

	gmacdev->DuplexMode = (cmd.duplex == DUPLEX_FULL)  ? FULLDUPLEX: HALFDUPLEX ;
	if(cmd.speed == SPEED_1000)
	        gmacdev->Speed      =   SPEED1000;
	else if(cmd.speed == SPEED_100)
		gmacdev->Speed      =   SPEED100;
	else
		gmacdev->Speed      =   SPEED10;

	}

	return gmacdev->Speed|(gmacdev->DuplexMode<<4);
}

static void synopGMAC_linux_cable_unplug_function(synopGMACPciNetworkAdapter *adapter)
{
	s32 data;
	synopGMACdevice *gmacdev = adapter->synopGMACdev;
	struct ethtool_cmd cmd;

	if (!mii_link_ok(&adapter->mii)) {
		if(gmacdev->LinkState)
		TR0("No Link\n");
		gmacdev->DuplexMode = 0;
		gmacdev->Speed = 0;
		gmacdev->LoopBackMode = 0;
		gmacdev->LinkState = 0;
	} else {
		data = synopGMAC_check_phy_init(adapter);

		if(gmacdev->LinkState != data){
			gmacdev->LinkState = data;
			synopGMAC_mac_init(gmacdev);

		TR0("Link is up in %s mode\n",(gmacdev->DuplexMode == FULLDUPLEX) ? "FULL DUPLEX": "HALF DUPLEX");
		if(gmacdev->Speed == SPEED1000)
			TR0("Link is with 1000M Speed \n");
		if(gmacdev->Speed == SPEED100)
			TR0("Link is with 100M Speed \n");
		if(gmacdev->Speed == SPEED10)
			TR0("Link is with 10M Speed \n");
		}
	}
}

/**
  * This sets up the transmit Descriptor queue in ring or chain mode.
  * This function is tightly coupled to the platform and operating system
  * Device is interested only after the descriptors are setup. Therefore this function
  * is not included in the device driver API. This function should be treated as an
  * example code to design the descriptor structures for ring mode or chain mode.
  * This function depends on the pcidev structure for allocation consistent dma-able memory in case of linux.
  * This limitation is due to the fact that linux uses pci structure to allocate a dmable memory
  *	- Allocates the memory for the descriptors.
  *	- Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor).
  *	- Initialize the Busy and Next descriptors to first descriptor address.
  * 	- Initialize the last descriptor with the endof ring in case of ring mode.
  *	- Initialize the descriptors in chain mode.
  * @param[in] pointer to synopGMACdevice.
  * @param[in] pointer to pci_device structure.
  * @param[in] number of descriptor expected in tx descriptor queue.
  * @param[in] whether descriptors to be created in RING mode or CHAIN mode.
  * \return 0 upon success. Error code upon failure.
  * \note This function fails if allocation fails for required number of descriptors in Ring mode, but in chain mode
  *  function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from this function
  *  user should for gmacdev->TxDescCount to see how many descriptors are there in the chain. Should continue further
  *  only if the number of descriptors in the chain meets the requirements
  */

//s32 synopGMAC_setup_tx_desc_queue(synopGMACdevice * gmacdev,struct pci_dev * pcidev,u32 no_of_desc, u32 desc_mode)
s32 synopGMAC_setup_tx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32 desc_mode)
{
	s32 i;
	DmaDesc * bf1;
	//flush_cache((unsigned long)gmacdev, sizeof(synopGMACdevice));

	DmaDesc *first_desc = NULL;
	//DmaDesc *second_desc = NULL;
	dma_addr_t dma_addr;
	gmacdev->TxDescCount = 0;

	TR("Total size of memory required for Tx Descriptors in Ring Mode = 0x%08x\n",((sizeof(DmaDesc) * no_of_desc)));
	first_desc = plat_alloc_consistent_dmaable_memory (gmacdev, sizeof(DmaDesc) * no_of_desc,&dma_addr);
	if(first_desc == NULL){
		printf("Error in Tx Descriptors memory allocation\n");
		return -ESYNOPGMACNOMEM;
	}

	gmacdev->TxDescCount = no_of_desc;
	gmacdev->TxDesc      = first_desc;
	gmacdev->TxDescDma  = dma_addr;

	TR("\n===Tx first_desc: %x\n",gmacdev->TxDesc);
	//gmacdev->FirstTxDesc = first_desc;

	for(i =0; i < gmacdev -> TxDescCount; i++){
		synopGMAC_tx_desc_init_ring(gmacdev->TxDesc + i, i == gmacdev->TxDescCount-1);
#if SYNOP_TOP_DEBUG
		printf("\n%02d %08x \n",i,(unsigned int)(gmacdev->TxDesc + i));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i))->status);
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->length));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->buffer1));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->buffer2));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->data1));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->data2));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->dummy1));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->dummy2));
		//		printf("%02d %08x \n",i,(unsigned int)(gmacdev->TxDesc + i));
		//		printf("%02d %08x \n",i,(unsigned int)(gmacdev->TxDesc + i));
#endif
	}

	gmacdev->TxNext = 0;
	gmacdev->TxBusy = 0;
	gmacdev->TxNextDesc = gmacdev->TxDesc;
	gmacdev->TxBusyDesc = gmacdev->TxDesc;
	gmacdev->BusyTxDesc  = 0;

	return -ESYNOPGMACNOERR;
}


/**
  * This sets up the receive Descriptor queue in ring or chain mode.
  * This function is tightly coupled to the platform and operating system
  * Device is interested only after the descriptors are setup. Therefore this function
  * is not included in the device driver API. This function should be treated as an
  * example code to design the descriptor structures in ring mode or chain mode.
  * This function depends on the pcidev structure for allocation of consistent dma-able memory in case of linux.
  * This limitation is due to the fact that linux uses pci structure to allocate a dmable memory
  *	- Allocates the memory for the descriptors.
  *	- Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor).
  *	- Initialize the Busy and Next descriptors to first descriptor address.
  * 	- Initialize the last descriptor with the endof ring in case of ring mode.
  *	- Initialize the descriptors in chain mode.
  * @param[in] pointer to synopGMACdevice.
  * @param[in] pointer to pci_device structure.
  * @param[in] number of descriptor expected in rx descriptor queue.
  * @param[in] whether descriptors to be created in RING mode or CHAIN mode.
  * \return 0 upon success. Error code upon failure.
  * \note This function fails if allocation fails for required number of descriptors in Ring mode, but in chain mode
  *  function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from this function
  *  user should for gmacdev->RxDescCount to see how many descriptors are there in the chain. Should continue further
  *  only if the number of descriptors in the chain meets the requirements
  */
s32 synopGMAC_setup_rx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32 desc_mode)
{
	s32 i;
	DmaDesc * bf1;
	DmaDesc *first_desc = NULL;
	//DmaDesc *second_desc = NULL;
	dma_addr_t dma_addr;
	//flush_cache((unsigned long)gmacdev, sizeof(synopGMACdevice));
	gmacdev->RxDescCount = 0;

	TR("total size of memory required for Rx Descriptors in Ring Mode = 0x%08x\n",((sizeof(DmaDesc) * no_of_desc)));
	first_desc = plat_alloc_consistent_dmaable_memory (gmacdev, sizeof(DmaDesc) * no_of_desc, &dma_addr);
	if(first_desc == NULL){
		printf("Error in Rx Descriptor Memory allocation in Ring mode\n");
		return -ESYNOPGMACNOMEM;
	}

	gmacdev->RxDescCount = no_of_desc;
	gmacdev->RxDesc      = (DmaDesc *)first_desc;
	gmacdev->RxDescDma   = dma_addr;
	//printf("c = 0x%x\n", dma_addr);
	//gmacdev->FirstRxDesc = first_desc;

	for(i =0; i < gmacdev -> RxDescCount; i++){
		synopGMAC_rx_desc_init_ring(gmacdev->RxDesc + i, i == gmacdev->RxDescCount-1);
#if SYNOP_TOP_DEBUG
		//TR("%02d %08x \n",i, (unsigned int)(gmacdev->RxDesc + i));
#endif
	}

	gmacdev->RxNext = 0;
	gmacdev->RxBusy = 0;
	gmacdev->RxNextDesc = gmacdev->RxDesc;
	gmacdev->RxBusyDesc = gmacdev->RxDesc;

	gmacdev->BusyRxDesc   = 0;

	return -ESYNOPGMACNOERR;
}


/**
 * Function to handle housekeeping after a packet is transmitted over the wire.
 * After the transmission of a packet DMA generates corresponding interrupt
 * (if it is enabled). It takes care of returning the sk_buff to the linux
 * kernel, updating the networking statistics and tracking the descriptors.
 * @param[in] pointer to net_device structure.
 * \return void.
 * \note This function runs in interrupt context
 */
void synop_handle_transmit_over(struct synopGMACNetworkAdapter * tp)
{
	struct	synopGMACNetworkAdapter *adapter;
	synopGMACdevice * gmacdev;
//	struct pci_dev *pcidev;
	s32 desc_index;
	u32 data1, data2;
	u32 status;
	u32 length1, length2;
	u64 dma_addr1, dma_addr2;
#ifdef ENH_DESC_8W
	u32 ext_status;
	u16 time_stamp_higher;
	u32 time_stamp_high;
	u32 time_stamp_low;
#endif

	adapter = tp;
	if(adapter == NULL){
#if SYNOP_TX_DEBUG
		TR("Unknown Device\n");
#endif
		return;
	}

	gmacdev = adapter->synopGMACdev;
	if(gmacdev == NULL){
#if SYNOP_TX_DEBUG
		TR("GMAC device structure is missing\n");
#endif
		return;
	}
#if SYNOP_TX_DEBUG
	TR("%s called \n",__FUNCTION__);
	//dumpdesc(gmacdev);
#endif

	/*Handle the transmit Descriptors*/
	do {
#ifdef ENH_DESC_8W
	desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2,&ext_status,&time_stamp_high,&time_stamp_low);
        synopGMAC_TS_read_timestamp_higher_val(gmacdev, &time_stamp_higher);
#else
	desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2);
#if 0
	printf("===handle transmit_over: %d\n",desc_index);
#endif
#endif
	//desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr, &length, &data1);
		if(desc_index >= 0 && data1 != 0){
#if SYNOP_TX_DEBUG
			printf("Finished Transmit at Tx Descriptor %d for data 0x%08x and buffer = %08x whose status is %08x \n", desc_index,data1,dma_addr1,status);
#endif
			#ifdef	IPC_OFFLOAD
			if(synopGMAC_is_tx_ipv4header_checksum_error(gmacdev, status)){
#if SYNOP_TX_DEBUG
			printf("Harware Failed to Insert IPV4 Header Checksum\n");
#else
#endif
			}
			if(synopGMAC_is_tx_payload_checksum_error(gmacdev, status)){
#if SYNOP_TX_DEBUG
			printf("Harware Failed to Insert Payload Checksum\n");
#else
#endif
			}
			#endif

			plat_free_memory((void *)(data1));	//sw:	data1 = buffer1

			if(synopGMAC_is_desc_valid(status)){
				adapter->synopGMACNetStats.tx_bytes += length1;
				adapter->synopGMACNetStats.tx_packets++;
			}
			else {
#if SYNOP_TX_DEBUG
#endif
				adapter->synopGMACNetStats.tx_errors++;
				adapter->synopGMACNetStats.tx_aborted_errors += synopGMAC_is_tx_aborted(status);
				adapter->synopGMACNetStats.tx_carrier_errors += synopGMAC_is_tx_carrier_error(status);
			}
		}	adapter->synopGMACNetStats.collisions += synopGMAC_get_tx_collision_count(status);
	} while(desc_index >= 0);
//	netif_wake_queue(netdev);
}




/**
 * Function to Receive a packet from the interface.
 * After Receiving a packet, DMA transfers the received packet to the system memory
 * and generates corresponding interrupt (if it is enabled). This function prepares
 * the sk_buff for received packet after removing the ethernet CRC, and hands it over
 * to linux networking stack.
 * 	- Updataes the networking interface statistics
 *	- Keeps track of the rx descriptors
 * @param[in] pointer to net_device structure.
 * \return void.
 * \note This function runs in interrupt context.
 */

void synop_handle_received_data(struct synopGMACNetworkAdapter* tp)
{
	struct synopGMACNetworkAdapter *adapter;
	synopGMACdevice * gmacdev;
//	struct PmonInet * pinetdev;
	s32 desc_index;
//	struct ifnet* ifp;
//	struct ether_header * eh;
	int i;
	char * ptr;
	u32 bf1;
	u32 data1;
	u32 data2;
	u32 len;
	u32 status;
	u64 dma_addr1;
	u64 dma_addr2;

	adapter = tp;
	if(adapter == NULL){
#if 1
		TR("Unknown Device\n");
#endif
		return;
	}

	gmacdev = adapter->synopGMACdev;
	if(gmacdev == NULL){
#if 1
		TR("GMAC device structure is missing\n");
#endif
		return;
	}
/*
	pinetdev = adapter->PInetdev;
	if(pinetdev == NULL){
#if SYNOP_RX_DEBUG
		TR("GMAC device structure is missing\n");
#endif
		return;
	}
	ifp = &(pinetdev->arpcom.ac_if);
*/
#if SYNOP_RX_DEBUG
	TR("%s\n",__FUNCTION__);
	//dumpdesc(gmacdev);
	dumpreg(regbase);
#endif


	/*Handle the Receive Descriptors*/
	do{
		desc_index = synopGMAC_get_rx_qptr(gmacdev, &status,&dma_addr1,NULL, &data1,&dma_addr2,NULL,&data2);
		TR("==handle rx desc%d\n",desc_index);
		if(desc_index >= 0 && data1 != 0){
#if 0
			printf("Received Data at Rx Descriptor %d for skb 0x%08x whose status is %08x\n",desc_index,dma_addr1,status);
#endif

			if(synopGMAC_is_rx_desc_valid(status)||SYNOP_PHY_LOOPBACK){

//				dma_addr1 =  plat_dma_map_single(gmacdev,data1,RX_BUF_SIZE,SYNC_R);
				dma_addr1 =  plat_dma_map_single(gmacdev,data1,RX_BUF_SIZE);
				len =  synopGMAC_get_rx_desc_frame_length(status) - 4; //Not interested in Ethernet CRC bytes

#if 0
				printf("==get pkg len: %d",len);
#endif

				NetReceive (data1, len);
				adapter->synopGMACNetStats.rx_packets++;
				adapter->synopGMACNetStats.rx_bytes += len;
			}
			else{
				adapter->synopGMACNetStats.rx_errors++;
				adapter->synopGMACNetStats.collisions       += synopGMAC_is_rx_frame_collision(status);
				adapter->synopGMACNetStats.rx_crc_errors    += synopGMAC_is_rx_crc(status);
				adapter->synopGMACNetStats.rx_frame_errors  += synopGMAC_is_frame_dribbling_errors(status);
				adapter->synopGMACNetStats.rx_length_errors += synopGMAC_is_rx_frame_length_errors(status);
			}

			desc_index = synopGMAC_set_rx_qptr(gmacdev,dma_addr1, RX_BUF_SIZE, (u32)data1,0,0,0);

			if(desc_index < 0){
#if 0
				TR("Cannot set Rx Descriptor for data1 %08x\n",(u32)data1);
#endif
				plat_free_memory((void *)data1);
			}

		}

	}while(desc_index >= 0);
}



/**
 * Interrupt service routing.
 * This is the function registered as ISR for device interrupts.
 * @param[in] interrupt number.
 * @param[in] void pointer to device unique structure (Required for shared interrupts in Linux).
 * @param[in] pointer to pt_regs (not used).
 * \return Returns IRQ_NONE if not device interrupts IRQ_HANDLED for device interrupts.
 * \note This function runs in interrupt context
 *
 */

//irqreturn_t synopGMAC_intr_handler(s32 intr_num, void * dev_id, struct pt_regs *regs)
int synopGMAC_intr_handler(struct synopGMACNetworkAdapter * tp)
{
        /*Kernels passes the netdev structure in the dev_id. So grab it*/
//        struct net_device *netdev;
        struct synopGMACNetworkAdapter *adapter;
        synopGMACdevice * gmacdev;
        u32 interrupt;
        u32 dma_status_reg;
        s32 status;
        u64 dma_addr;

        adapter  = tp;
        if(adapter == NULL){
                TR("Adapter Structure Missing\n");
                return -1;
        }

        gmacdev = adapter->synopGMACdev;
        if(gmacdev == NULL){

                TR("GMAC device structure Missing\n");
                return -1;
        }

        /*Read the Dma interrupt status to know whether the interrupt got generated by our device or not*/
        dma_status_reg = synopGMACReadReg(gmacdev->DmaBase, DmaStatus);
//              TR("%s:Dma Status Reg: 0x%08x\n",__FUNCTION__,dma_status_reg);


        if(dma_status_reg == 0)
                return 0;

        synopGMAC_disable_interrupt_all(gmacdev);

//      dumpreg(regbase);


        if(dma_status_reg & GmacPmtIntr){
                TR("%s:: Interrupt due to PMT module\n",__FUNCTION__);
                //synopGMAC_linux_powerup_mac(gmacdev);
        }

        if(dma_status_reg & GmacMmcIntr){
                TR("%s:: Interrupt due to MMC module\n",__FUNCTION__);
                TR("%s:: synopGMAC_rx_int_status = %08x\n",__FUNCTION__,synopGMAC_read_mmc_rx_int_status(gmacdev));
                TR("%s:: synopGMAC_tx_int_status = %08x\n",__FUNCTION__,synopGMAC_read_mmc_tx_int_status(gmacdev));
        }

        if(dma_status_reg & GmacLineIntfIntr)
        {
                synopGMAC_linux_cable_unplug_function(adapter);
        }
        /*Now lets handle the DMA interrupts*/
        interrupt = synopGMAC_get_interrupt_type(gmacdev);
//sw
        if(interrupt == 0)
                return 0;

//      TR("%s:Interrupts to be handled: 0x%08x\n",__FUNCTION__,interrupt);

        if(interrupt & synopGMACDmaError){

                u8 mac_addr[6] = DEFAULT_MAC_ADDRESS;//after soft reset, configure the MAC address to default value
               printf("%s::Fatal Bus Error Inetrrupt Seen\n",__FUNCTION__);
                printf("====DMA error!!!\n");

                synopGMAC_disable_dma_tx(gmacdev);
                synopGMAC_disable_dma_rx(gmacdev);

                synopGMAC_take_desc_ownership_tx(gmacdev);
                synopGMAC_take_desc_ownership_rx(gmacdev);

                synopGMAC_init_tx_rx_desc_queue(gmacdev);

                synopGMAC_reset(gmacdev);//reset the DMA engine and the GMAC ip

                synopGMAC_set_mac_addr(gmacdev,GmacAddr0High,GmacAddr0Low, mac_addr);
                synopGMAC_dma_bus_mode_init(gmacdev,DmaFixedBurstEnable| DmaBurstLength8 | DmaDescriptorSkip2 );
                synopGMAC_dma_control_init(gmacdev,DmaStoreAndForward);
                synopGMAC_init_rx_desc_base(gmacdev);
                synopGMAC_init_tx_desc_base(gmacdev);
                synopGMAC_mac_init(gmacdev);
                synopGMAC_enable_dma_rx(gmacdev);
                synopGMAC_enable_dma_tx(gmacdev);

        }


        if(interrupt & synopGMACDmaRxNormal)
        {
#if 0
                printf("%s:: Rx Normal \n", __FUNCTION__);
#endif

#if 0
                rx_test_count += 1;
                printf("Rx: total%d packets!\n",rx_test_count);
#endif
//              dumpreg(regbase);
                synop_handle_received_data(adapter);
        }

        if(interrupt & synopGMACDmaRxAbnormal){
		DmaDesc * rxdesc = gmacdev->RxBusyDesc;
                printf("%s::Abnormal Rx Interrupt Seen\n",__FUNCTION__);
	        printf("rxdesc=0x%lx buffer1=0x%lx\n",(long)rxdesc,(long)rxdesc->buffer1);


                #if 1

               if(GMAC_Power_down == 0){        // If Mac is not in powerdown
                adapter->synopGMACNetStats.rx_over_errors++;
                /*Now Descriptors have been created in synop_handle_received_data(). Just issue a poll demand to resume DMA operation*/
                synopGMACWriteReg(gmacdev->DmaBase, DmaStatus ,0x80);   //sw: clear the rxb ua bit
                synopGMAC_resume_dma_rx(gmacdev);//To handle GBPS with 12 descriptors
                }
                #endif
        }

        if(interrupt & synopGMACDmaRxStopped){
                printf("%s::Receiver stopped seeing Rx interrupts\n",__FUNCTION__); //Receiver gone in to stopped state
                #if 1
                if(GMAC_Power_down == 0){       // If Mac is not in powerdown
                adapter->synopGMACNetStats.rx_over_errors++;
/*
                do{
                        struct sk_buff *skb = alloc_skb(netdev->mtu + ETHERNET_HEADER + ETHERNET_CRC, GFP_ATOMIC);
                        if(skb == NULL){
                                TR("%s::ERROR in skb buffer allocation Better Luck Next time\n",__FUNCTION__);
                                break;
                                //                      return -ESYNOPGMACNOMEM;
                        }

                        dma_addr = pci_map_single(pcidev,skb->data,skb_tailroom(skb),PCI_DMA_FROMDEVICE);
                        status = synopGMAC_set_rx_qptr(gmacdev,dma_addr, skb_tailroom(skb), (u32)skb,0,0,0);
                        TR("%s::Set Rx Descriptor no %08x for skb %08x \n",__FUNCTION__,status,(u32)skb);
                        if(status < 0)
                                dev_kfree_skb_irq(skb);//changed from dev_free_skb. If problem check this again--manju

                }while(status >= 0);
*/
                do{
                        u32 skb = (u32)plat_alloc_memory(RX_BUF_SIZE);          //should skb aligned here?
                        if(skb == NULL){
                                TR0("ERROR in skb buffer allocation\n");
                                break;
//                              return -ESYNOPGMACNOMEM;
                        }

                        //dma_addr = (u32)skb;
                        dma_addr = plat_dma_map_single(gmacdev,skb,RX_BUF_SIZE);
                        status = synopGMAC_set_rx_qptr(gmacdev,dma_addr,RX_BUF_SIZE, (u32)skb,0,0,0);
                        printf("%s::Set Rx Descriptor no %08x for skb %08x \n",__FUNCTION__,status,(u32)skb);
                        if(status < 0)
                        {
                                printf("==%s:no free\n",__FUNCTION__);
                                plat_free_memory((void *)skb);
                        }
                }while(status >= 0);

                        synopGMAC_enable_dma_rx(gmacdev);
                }
                #endif
        }

        if(interrupt & synopGMACDmaTxNormal)
        {
                //xmit function has done its job

#if 0
                tx_normal_test_count += 1;
                printf("Tx: %dtotal normal packets!\n",tx_normal_test_count);
#endif
#if 0
                printf("%s::Finished Normal Transmission \n",__FUNCTION__);
//              dumpreg(regbase);
#endif
#if SYNOP_TX_DEBUG
                //printf("Gmac_intr: dma_status = 0x%08x\n",dma_status_reg);
#endif
                synop_handle_transmit_over(adapter);    //Do whatever you want after the transmission is over
        }

        if(interrupt & synopGMACDmaTxAbnormal){
#if SYNOP_TX_TEST
                tx_abnormal_test_count += 1;
               // printf("Tx: %d abnormal packets!\n",tx_abnormal_test_count);
#endif
                //printf("%s::Abnormal Tx Interrupt Seen\n",__FUNCTION__);
//              dumpreg(regbase);
                #if 1
               if(GMAC_Power_down == 0){        // If Mac is not in powerdown
                synop_handle_transmit_over(adapter);
                }
                #endif
        }



        if(interrupt & synopGMACDmaTxStopped){
#if SYNOP_TX_TEST
                tx_stopped_test_count += 1;
                printf("Tx: %d stopped packets!\n",tx_stopped_test_count);
#endif
                printf("%s::Transmitter stopped sending the packets\n",__FUNCTION__);
                #if 1
               if(GMAC_Power_down == 0){        // If Mac is not in powerdown
                synopGMAC_disable_dma_tx(gmacdev);
                synopGMAC_take_desc_ownership_tx(gmacdev);

                synopGMAC_enable_dma_tx(gmacdev);
//              netif_wake_queue(netdev);
                TR("%s::Transmission Resumed\n",__FUNCTION__);
                }
                #endif
        }
//      synopGMAC_clear_interrupt(gmacdev);

        /* Enable the interrrupt before returning from ISR*/
//        synopGMAC_enable_interrupt(gmacdev,DmaIntEnable);
        return 0;
}
/**
 * Function used when the interface is opened for use.
 * We register synopGMAC_linux_open function to linux open(). Basically this
 * function prepares the the device for operation . This function is called whenever ifconfig (in Linux)
 * activates the device (for example "ifconfig eth0 up"). This function registers
 * system resources needed
 * 	- Attaches device to device specific structure
 * 	- Programs the MDC clock for PHY configuration
 * 	- Check and initialize the PHY interface
 *	- ISR registration
 * 	- Setup and initialize Tx and Rx descriptors
 *	- Initialize MAC and DMA
 *	- Allocate Memory for RX descriptors (The should be DMAable)
 * 	- Initialize one second timer to detect cable plug/unplug
 *	- Configure and Enable Interrupts
 *	- Enable Tx and Rx
 *	- start the Linux network queue interface
 * @param[in] pointer to net_device structure.
 * \return Returns 0 on success and error status upon failure.
 * \callgraph
 */

s32 synopGMAC_linux_open(struct eth_device *dev)
{
	s32 status = 0;
	s32 retval = 0;
	int delay = 100;

	u64 dma_addr;
	u32 skb;	//sw	we just use the name skb in pomn
	u32 skb1;
	struct synopGMACNetworkAdapter *adapter = dev->priv;
        synopGMACdevice * gmacdev;
	TR0("%s called \n",__FUNCTION__);
	gmacdev = (synopGMACdevice *)adapter->synopGMACdev;



	/*Now platform dependent initialization.*/

	//Lets reset the IP
	synopGMAC_reset(gmacdev);

	synopGMAC_set_mac_addr(gmacdev,GmacAddr0High,GmacAddr0Low, dev->enetaddr);

	//Lets read the version of ip in to device structure
	synopGMAC_read_version(gmacdev);

	synopGMAC_get_mac_addr(adapter->synopGMACdev,GmacAddr0High,GmacAddr0Low, dev->enetaddr);

	//Check for Phy initialization
	synopGMAC_set_mdc_clk_div(gmacdev,GmiiCsrClk3);
	gmacdev->ClockDivMdc = synopGMAC_get_mdc_clk_div(gmacdev);

	//dumpphyreg(regbase);

//	set_lpmode(gmacdev);
//	set_phyled(gmacdev);


#if SYNOP_TOP_DEBUG
	printf("check phy init status = 0x%x\n",status);
#endif



	//Set up the tx and rx descriptor queue/ring
//sw
	synopGMAC_setup_tx_desc_queue(gmacdev,TRANSMIT_DESC_SIZE, RINGMODE);
	synopGMAC_init_tx_desc_base(gmacdev);	//Program the transmit descriptor base address in to DmaTxBase addr

#if SYNOP_TOP_DEBUG
	dumpreg(regbase);
#endif

	synopGMAC_setup_rx_desc_queue(gmacdev,RECEIVE_DESC_SIZE, RINGMODE);
	synopGMAC_init_rx_desc_base(gmacdev);	//Program the transmit descriptor base address in to DmaTxBase addr



#if SYNOP_TOP_DEBUG
	dumpphyreg(regbase);
#endif





#ifdef ENH_DESC_8W
	synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength32 | DmaDescriptorSkip2 | DmaDescriptor8Words ); //pbl32 incr with rxthreshold 128 and Desc is 8 Words
#else
	synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength4 | DmaDescriptorSkip1 );                      //pbl4 incr with rxthreshold 128
#endif

	synopGMAC_dma_control_init(gmacdev,DmaStoreAndForward |DmaTxSecondFrame|DmaRxThreshCtrl128 );


	//Initialize the mac interface
	synopGMAC_check_phy_init(adapter);
	synopGMAC_mac_init(gmacdev);
	//dumpreg(regbase);


	synopGMAC_pause_control(gmacdev); // This enables the pause control in Full duplex mode of operation

//int i=0;
	do{
		skb = (u32)plat_alloc_memory(RX_BUF_SIZE);		//should skb aligned here?
		if(skb == NULL){
			TR0("ERROR in skb buffer allocation\n");
			break;
//			return -ESYNOPGMACNOMEM;
		}

//		dma_addr = plat_dma_map_single(gmacdev,skb,RX_BUF_SIZE,SYNC_R);
		dma_addr = plat_dma_map_single(gmacdev,skb,RX_BUF_SIZE);


		status = synopGMAC_set_rx_qptr(gmacdev,dma_addr,RX_BUF_SIZE, (u32)skb,0,0,0);
		if(status < 0)
		{
			plat_free_memory((void *)skb);
		}
//gmacdev->skb_array[i++] = skb;
	}while(status >= 0 && status < RECEIVE_DESC_SIZE-1);

#if 0
	dumpdesc(gmacdev);
#endif

	synopGMAC_clear_interrupt(gmacdev);
	/*
	Disable the interrupts generated by MMC and IPC counters.
	If these are not disabled ISR should be modified accordingly to handle these interrupts.
	*/
	synopGMAC_disable_mmc_tx_interrupt(gmacdev, 0xFFFFFFFF);
	synopGMAC_disable_mmc_rx_interrupt(gmacdev, 0xFFFFFFFF);
	synopGMAC_disable_mmc_ipc_rx_interrupt(gmacdev, 0xFFFFFFFF);

//sw	no interrupts in pmon
	//synopGMAC_enable_interrupt(gmacdev,DmaIntEnable);
	synopGMAC_disable_interrupt_all(gmacdev);


	//dumpreg(regbase);

	synopGMAC_enable_dma_rx(gmacdev);
	synopGMAC_enable_dma_tx(gmacdev);
#if 0
	dumpreg(regbase);
#endif

//	synopGMAC_rx_enable(gmacdev);

#if 0
	dumpphyreg(regbase);
#endif

#if SYNOP_PHY_LOOPBACK
{
		gmacdev->LinkState = LINKUP;
		gmacdev->DuplexMode = FULLDUPLEX;
	        gmacdev->Speed      =   SPEED1000;
}
#endif
        plat_delay(DEFAULT_LOOP_VARIABLE);
	synopGMAC_check_phy_init(adapter);
	synopGMAC_mac_init(gmacdev);

	synopGMAC_linux_cable_unplug_function(adapter);
//		PInetdev->sc_ih = pci_intr_establish(0, 0, IPL_NET, synopGMAC_intr_handler, adapter, 0);
//		TR("register poll interrupt: gmac 0\n");

	return retval;

}

/**
 * Function to transmit a given packet on the wire.
 * Whenever Linux Kernel has a packet ready to be transmitted, this function is called.
 * The function prepares a packet and prepares the descriptor and
 * enables/resumes the transmission.
 * @param[in] pointer to sk_buff structure.
 * @param[in] pointer to net_device structure.
 * \return Returns 0 on success and Error code on failure.
 * \note structure sk_buff is used to hold packet in Linux networking stacks.
 */

//s32 synopGMAC_linux_xmit_frames(struct sk_buff *skb, struct net_device *netdev)
s32 synopGMAC_linux_xmit_frames(struct eth_device *dev, volatile void *packet, int length)
//s32 synopGMAC_linux_xmit_frames(struct ifnet* ifp)
{
	s32 status = 0;
	u64 dma_addr;
	u32 offload_needed = 0;
	u32 skb;
	u32 index;
	DmaDesc *dpr = NULL;
	int len = length;
	int i;
	char * ptr;
//	struct mbuf *mb_head;	//sw	we just use the name skb
//	struct ether_header * eh;

	//u32 flags;
	struct synopGMACNetworkAdapter *adapter;
	synopGMACdevice * gmacdev;
//	struct pci_dev * pcidev;
#if SYNOP_TX_DEBUG
	TR("%s called \n",__FUNCTION__);
	printf("===xmit  yeh!\n");
#endif

//	adapter = (struct synopGMACNetworkAdapter *) ifp->if_softc;
	adapter = (struct synopGMACNetworkAdapter *) dev->priv;
	if(adapter == NULL)
		return -1;

	gmacdev = (synopGMACdevice *) adapter->synopGMACdev;
	if(gmacdev == NULL)
		return -1;
#if SYNOP_TX_DEBUG
	printf("xmit: TxBusy = %d\tTxNext = %d\n",gmacdev->TxBusy,gmacdev->TxNext);
#endif

//		while(ifp->if_snd.ifq_head != NULL){
			if(!synopGMAC_is_desc_owned_by_dma(gmacdev->TxNextDesc))
			{

				skb = (u32)plat_alloc_memory(TX_BUF_SIZE);
				if(skb == 0)
				{
//#if SYNOP_TX_DEBUG
					printf("===error in alloc bf1\n");
//#endif
					return -1;
				}
//				IF_DEQUEUE(&ifp->if_snd, mb_head);

				/*Now we have skb ready and OS invoked this function. Lets make our DMA know about this*/



//				len = mb_head->m_pkthdr.len;


				//sw: i don't know weather it's right
//				m_copydata(mb_head, 0, len,(char *)skb);
//				dma_addr = plat_dma_map_single(gmacdev,skb,len,SYNC_W);
				memcpy((void *)skb, packet, len);
				dma_addr = plat_dma_map_single(gmacdev,skb,len);

				/*
				   if(len < 64)
				   len = 64;
				 */

#if SYNOP_TX_DEBUG
				printf("==tx pkg len: %d",len);
#endif
#if 0 //SYNOP_TX_DEBUG
				//sw: dbg
				eh = mtod(skb, struct ether_header *);
				dumppkghd(eh,0);

				for(i = 0;i < len;i++)
				{
					ptr = (u32)bf1;
					printf(" %02x",*(ptr+i));
				}
				printf("\n");
#endif


//				m_freem(mb_head);


				//		status = synopGMAC_set_tx_qptr(gmacdev, dma_addr, TX_BUF_SIZE, bf1,0,0,0,offload_needed);
//				status = synopGMAC_set_tx_qptr(gmacdev, dma_addr, len, skb,0,0,0,offload_needed,&index,dpr);
				status = synopGMAC_set_tx_qptr(gmacdev, dma_addr, len, skb,0,0,0,offload_needed,&index,dpr);

#if 0
				printf("using TX descriptor %d \n",status);
#endif


						//dumpdesc(gmacdev);
				if(status < 0){
#if 1
					printf("%s No More Free Tx Descriptors\n",__FUNCTION__);
#endif
			plat_free_memory((void *)skb);
					//			dev_kfree_skb (skb); //with this, system used to freeze.. ??
					//return -EBUSY;
					return -16;
				}
			}
#if SYNOP_TX_DEBUG
			else
				printf("===%x: next txDesc belongs to DMA don't set it\n",gmacdev->TxNextDesc);
#endif
//		}

	/*Now force the DMA to start transmission*/
#if SYNOP_TX_DEBUG
		{
			u32 data;
			data = synopGMACReadReg(gmacdev->DmaBase, 0x48);
			printf("TX DMA DESC ADDR = 0x%x\n",data);
		}
#endif
		/*
	synopGMAC_tx_enable(gmacdev);
	synopGMAC_enable_dma_tx(gmacdev);
	synopGMAC_resume_dma_tx(gmacdev);
	*/
	synopGMAC_resume_dma_tx(gmacdev);
	//printf("%02d %08x %08x %08x %08x %08x %08x %08x\n",index,(u32)dpr,dpr->status,dpr->length,dpr->buffer1,dpr->buffer2,dpr->data1,dpr->data2);
	return -ESYNOPGMACNOERR;
}

int init_phy(synopGMACdevice *gmacdev)
{
	u16 data;

	synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,2,&data);
	/*set 88e1111 clock phase delay*/
	if(data == 0x141)
	 rtl88e1111_config_init(gmacdev);
	else if(data == 0x22)
	{
		synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0xc,0xf0f0);
		synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0xb,0x8104);
		synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0xb,0x104);
	}
		return 0;
}
/*
void dumppkghd(struct ether_header *eh,int tp)
{
		int i;
//sw: dbg
		if(tp == 1)
	       		printf("\n===Rx:  pkg dst:  ");
		else
	       		printf("\n===Tx:  pkg dst:  ");

		for(i = 0;i < 6;i++)
	       		printf(" %02x",eh->ether_dhost[i]);

		if(tp == 1)
			printf("\n===Rx:  pkg sst:  ");
		else
			printf("\n===Tx:  pkg sst:  ");

		for(i = 0;i < 6;i++)
	       		printf(" %02x",eh->ether_shost[i]);

		if(tp == 1)
			printf("\n===Rx:  pkg type:  ");
		else
			printf("\n===Tx:  pkg type:  ");
		printf(" %12x",eh->ether_type);
		printf("\n");

//dbg
}
*/



s32 synopGMAC_dummy_reset(struct eth_device *dev)
//s32 synopGMAC_dummy_reset(struct ifnet *ifp)
{
	struct synopGMACNetworkAdapter * adapter;
	synopGMACdevice	* gmacdev;
	DmaDesc * desc;

	adapter = (struct synopGMACNetworkAdapter *)dev->priv;
	gmacdev = adapter->synopGMACdev;
//printf("1\n");
	return synopGMAC_reset(gmacdev);
}


s32 synopGMAC_dummy_ioctl(struct ifnet *ifp)
{
//	printf("==dummy ioctl\n");
	return 0;
}
//sw:	i just copy this function from rtl8169.c


void dumpdesc(synopGMACdevice	* gmacdev)
{
	int i;

	printf("\n===dump Tx desc");
	for(i =0; i < gmacdev -> TxDescCount; i++){
		printf("\n%02d %08x : ",i,(unsigned int)(gmacdev->TxDesc + i));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i))->status);
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->length));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->buffer1));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->buffer2));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->data1));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->data2));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->dummy1));
		printf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->dummy2));
	}
	printf("\n===dump Rx desc");
	for(i =0; i < gmacdev -> RxDescCount; i++){
		printf("\n%02d %08x : ",i,(unsigned int)(gmacdev->RxDesc + i));
		printf("%08x ",(unsigned int)((gmacdev->RxDesc + i))->status);
		printf("%08x ",(unsigned int)((gmacdev->RxDesc + i)->length));
		printf("%08x ",(unsigned int)((gmacdev->RxDesc + i)->buffer1));
		printf("%08x ",(unsigned int)((gmacdev->RxDesc + i)->buffer2));
		printf("%08x ",(unsigned int)((gmacdev->RxDesc + i)->data1));
		printf("%08x ",(unsigned int)((gmacdev->RxDesc + i)->data2));
		printf("%08x ",(unsigned int)((gmacdev->RxDesc + i)->dummy1));
		printf("%08x ",(unsigned int)((gmacdev->RxDesc + i)->dummy2));
	}

	printf("\n\n");

}


void dumpreg(u64 gbase)
{
	int i;
	int k;
	u32 data;

	printf("\n==== gmac:0 dumpreg\n");
	for (i = 0,k = 0; i < 0xbc; i = i+4,k++)
	{
		data = synopGMACReadReg(gbase, i );
		printf("  reg:%2x value:%8x  ",i,data);
		if(k%4 == 3)
			printf("\n");
	}
	printf("\n");
	for (i = 0xc0,k = 0; i < 0xdc; i = i+4,k++){
		data = synopGMACReadReg(gbase, i );
		printf("  reg:%2x value:%8x  ",i,data);
		if(k%4 == 3)
			printf("\n");
	}
	printf("\n");

	for (i = 0,k = 0; i < 0x5c; i = i+4,k++){
		data = synopGMACReadReg(gbase+0x1000, i );
		printf("  reg:%2x value:%8x  ",i,data);
		if(k%4 == 3)
			printf("\n");

	}
	printf("\n\n");
}

void dumpphyreg(gbase)
{
	u16 data;
	int i;
	printf("===dump mii phy regs of GMAC: 0\n");
	for(i = 0x0; i <= 0x1f; i++)
	{
		//synopGMAC_read_phy_reg(gbase+0x1000,0x10,i, &data);
		synopGMAC_read_phy_reg(gbase,1,i, &data);
		printf("  mii phy reg: %x    value: %x  \n",i,data);
	}
	printf("\n");
}

/*
void setphysreg0(synopGMACdevice * gmacdev,int reg,int val)
{
//sw: exp-reg 111 shoud be 7;
	int i;
	u16 data0[5] = {0x7007,0x4007,0x2007,0x1007,0x0007};
	u16 sreg0[5] = {0x111,0x100,0x010,0x001,0x000};
	u16 data;

	for(i = 0;i < 5;i++)
	{
		if(sreg0[i] == reg)
			break;
	}

	synopGMAC_write_phy_reg(gmacdev->MacBase,1,0x18, data0[i]);
	synopGMAC_read_phy_reg(gmacdev->MacBase,1,0x18, &data);

	synopGMAC_write_phy_reg(gmacdev->MacBase,1,reg, val);
}
*/


int set_lpmode(synopGMACdevice * gmacdev)
{
	u16 data;
	int status;
	int delay;

	printf("===reset phy...\n");

	status = synopGMAC_read_phy_reg(gmacdev->MacBase,1,0,&data);
//sw: if you set bit 13,it resets!!
//	data = 0x6000;
	data = 0x4040;
	printf("===set phy loopback mode , reg0: %x\n",data);

	status = synopGMAC_write_phy_reg(gmacdev->MacBase,1,0,data);
	if(status != 0)
		return 0;

	delay = 200;
	while(delay > 0)
		delay--;

	status = synopGMAC_read_phy_reg(gmacdev->MacBase,1,0,&data);
	printf("===phy loopback mode , reg0: %x\n",data);

	return 1;

}


int set_phyled(synopGMACdevice * gmacdev)
{
	synopGMAC_write_phy_reg(gmacdev->MacBase,1,0x1c, 0xb842);
	return 0;
}


void reg_init(synopGMACdevice * gmacdev)
{
	u32 data;

	synopGMACWriteReg(gmacdev->DmaBase, DmaBusMode,0x0);

	data = synopGMACReadReg(gmacdev->DmaBase, DmaBusMode);
  	data |= 0x400;
	synopGMACWriteReg(gmacdev->DmaBase, DmaBusMode,data);

	data = synopGMACReadReg(gmacdev->MacBase, GmacConfig );
  	data |= 0x800;
	synopGMACWriteReg(gmacdev->MacBase, GmacConfig,data);

	data = synopGMACReadReg(gmacdev->MacBase, GmacFrameFilter );
  	data |= 0x80000000;
	synopGMACWriteReg(gmacdev->MacBase, GmacFrameFilter ,data);


	data = synopGMACReadReg(gmacdev->DmaBase, DmaControl );
  	data |= 0x2000;
	synopGMACWriteReg(gmacdev->DmaBase, DmaControl,data);

	data = synopGMACReadReg(gmacdev->MacBase, GmacConfig );
  	data |= 0x4;
	synopGMACWriteReg(gmacdev->MacBase, GmacConfig,data);

	data = synopGMACReadReg(gmacdev->MacBase, GmacConfig );
  	data |= 0x8;
	synopGMACWriteReg(gmacdev->MacBase, GmacConfig,data);

	printf("====done! OK!\n");

}

static int mdio_read(synopGMACPciNetworkAdapter *adapter, int addr, int reg)
{
	synopGMACdevice * gmacdev;
	u16 data;
	gmacdev = adapter->synopGMACdev;

	synopGMAC_read_phy_reg((u32 *)gmacdev->MacBase,addr,reg, &data);
	return data;
}

static void mdio_write(synopGMACPciNetworkAdapter *adapter, int addr, int reg, int data)
{
	synopGMACdevice * gmacdev;
	gmacdev = adapter->synopGMACdev;
	synopGMAC_write_phy_reg((u32 *)gmacdev->MacBase,addr,reg,data);
}




void gmac_halt(struct eth_device *dev)
{
	struct synopGMACNetworkAdapter *adapter;
	synopGMACdevice * gmacdev;
	adapter = (struct synopGMACNetworkAdapter *) dev->priv;
	if(adapter == NULL)
		return;

	gmacdev = (synopGMACdevice *) adapter->synopGMACdev;
	if(gmacdev == NULL)
		return;
	//synopGMAC_dummy_reset(dev);
	synopGMAC_disable_interrupt_all(gmacdev);
	synopGMAC_disable_dma_tx(gmacdev);
	synopGMAC_disable_dma_rx(gmacdev);

	synopGMAC_take_desc_ownership_tx(gmacdev);
	synopGMAC_take_desc_ownership_rx(gmacdev);
}

static int gmac_init(struct eth_device *dev, bd_t * bd)
{
	return synopGMAC_linux_open(dev);
}


static int gmac_recv(struct eth_device *dev)
{
	synopGMAC_intr_handler(dev->priv);
	return 0;
}

/* Send a data block via Ethernet. */
static int gmac_send(struct eth_device *dev, volatile void *packet, int length)
{
	struct synopGMACNetworkAdapter *adapter;
	adapter = (struct synopGMACNetworkAdapter *) dev->priv;
        synopGMAC_linux_cable_unplug_function(adapter);
	synopGMAC_linux_xmit_frames(dev, packet, length);
	synop_handle_transmit_over(dev->priv);
	return 0;
}

/**
 * Function to initialize the Linux network interface.
 *
 * Linux dependent Network interface is setup here. This provides
 * an example to handle the network dependent functionality.
 *
 * \return Returns 0 on success and Error code on failure.
 */
s32  gmac_initialize(char *dev_name, void *base_addr)
//s32  synopGMAC_init_network_interface(char* dev_name,u64 base_addr)
{
//varables added by sw

	static u8 mac_addr0[6];
	u8 macaddr[6];
	static int inited = 0;
	int i;
	u16 data;
	struct synopGMACNetworkAdapter * synopGMACadapter;
	if(!inited)
	{
		u8 v = 0;
		char *s=getenv("ethaddr");
		if(s){
			int allz,allf;

			for(i = 0, allz = 1, allf = 1; i < 6; i++) {
				gethex(&v, s, 2);
				macaddr[i] = v;
				s += 3;         /* Don't get to fancy here :-) */
				if(v != 0) allz = 0;
				if(v != 0xff) allf = 0;
			}
			if(!allz && !allf)
				memcpy(mac_addr0, macaddr, 6);
		}
		inited = 1;
	}

	TR("Now Going to Call register_netdev to register the network interface for GMAC core\n");
	synopGMACadapter = (struct synopGMACNetworkAdapter * )plat_alloc_memory(sizeof (struct synopGMACNetworkAdapter));
//sw:	should i put sync_cache here?
	memset((char *)synopGMACadapter ,0, sizeof (struct synopGMACNetworkAdapter));

	synopGMACadapter->synopGMACdev    = NULL;

	/*Allocate Memory for the the GMACip structure*/
	synopGMACadapter->synopGMACdev = (synopGMACdevice *) plat_alloc_memory(sizeof (synopGMACdevice));
	memset((char *)synopGMACadapter->synopGMACdev ,0, sizeof (synopGMACdevice));
	if(!synopGMACadapter->synopGMACdev){
		printf("Error in Memory Allocataion \n");
	}

	synopGMAC_attach(synopGMACadapter->synopGMACdev,(u64) base_addr + MACBASE,(u64) base_addr + DMABASE, DEFAULT_PHY_BASE,mac_addr0);
	//synopGMAC_get_mac_addr(synopGMACadapter->synopGMACdev, GmacAddr0High, GmacAddr0Low, macaddr);
#if 0
	dumpphyreg(regbase);
#endif

	init_phy(synopGMACadapter->synopGMACdev);
//	testphyreg(synopGMACadapter->synopGMACdev);
	synopGMAC_reset(synopGMACadapter->synopGMACdev);


#if 0
	dumpreg(regbase);
	dumpphyreg(regbase);
#if SYNOP_GMAC0
	dumpdesc(synopGMACadapter->synopGMACdev);
#endif
#endif

	/* MII setup */
	synopGMACadapter->mii.phy_id_mask = 0x1F;
	synopGMACadapter->mii.reg_num_mask = 0x1F;
	synopGMACadapter->mii.dev = synopGMACadapter;
	synopGMACadapter->mii.mdio_read = mdio_read;
	synopGMACadapter->mii.mdio_write = mdio_write;
	synopGMACadapter->mii.phy_id = synopGMACadapter->synopGMACdev->PhyBase;
	synopGMACadapter->mii.supports_gmii = mii_check_gmii_support(&synopGMACadapter->mii);

struct eth_device *dev;
        dev = malloc(sizeof(*dev));
        if (!dev) {
                return 0;
        }
        memset(dev, 0, sizeof(*dev));

        dev->iobase = base_addr;
	dev->priv = synopGMACadapter;

        bcopy(dev_name, dev->name, 16);
        dev->enetaddr[0] = mac_addr0[0];
        dev->enetaddr[1] = mac_addr0[1];
        dev->enetaddr[2] = mac_addr0[2];
        dev->enetaddr[3] = mac_addr0[3];
        dev->enetaddr[4] = mac_addr0[4];
        dev->enetaddr[5] = mac_addr0[5];
#if 0
	int q;
	for(q=0;q<6;q++)	printf("a%x\t", dev->enetaddr[q]);
#endif

        dev->init = gmac_init;
        dev->halt = gmac_halt;
        dev->send = gmac_send;
        dev->recv = gmac_recv;

        eth_register(dev);

	return 0;
}

